package com.patterns.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;

/**
 * 动态代理，使用jdk自动
 * @author fwj
 * date 2021/4/22 10:34
 **/
public class Tank implements Movable {

    /**
     * 模拟坦克移动了一段时间
     */
    @Override
    public void move() {
        System.out.println("Tank moving claclaclacla...");
        try {
            Thread.sleep(new Random().nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Tank tank = new Tank();

        //reflection 通过二进制字节码分析累的属性和方法

        //参数说明：第一个：被代理对象的ClassLoader 第二个：实现的接口 第三个：被代理对象方法调用时如何处理
        //java会自动生成一个proxy类，可以设置下面的参数，把生产的proxy类输出，可以看看这个proxy是怎么写的
//        System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles"."true");
        Movable m = (Movable) Proxy.newProxyInstance(Tank.class.getClassLoader(),
                new Class[]{Movable.class},
                new LogHandler(tank));

        // 这里实际上是调用了生产proxy类的move方法
        m.move();
    }
}

/**
 * 被代理对象方法调用时如何处理
 * 也可是直接用匿名内部类
 */
class LogHandler implements InvocationHandler {

    Tank tank;

    public LogHandler(Tank tank) {
        this.tank = tank;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("method " + method.getName() + "start...");
        Object o = method.invoke(tank, args);
        System.out.println("method " + method.getName() + "end.");
        return o;
    }
}


interface Movable {
    void move();
}